﻿// TCP协议.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>


#include <winsock.h>
#pragma comment(lib,"Ws2_32.lib")



/*
TCP协议：
    网络              网卡

    网卡是硬件       操作系统之上对应硬件的东西   叫做设备驱动程序

    网络通信：
        借助网络设备实现两个应用程序(exe)之间的数据传输
        这两个程序可以运行于  两个主机之上

CS架构      客户端  服务器
BS架构		浏览器  服务器


单工：单向
双工：双向
半双工：发的时候不能收，收的时候不能发
全双工：同时收发



编程模型;
    Server                                           Client
0.确定协议版本号                                    0.确定协议版本号
                                WSAStartup
1.创建socket（网卡）                                1.创建socket（网卡)
                                socket
2.创建服务器协议地址族                              2.确定服务器协议地址族
                                sockaddr_in
3.绑定       
                                bind
4.监听      
                                listen
5.接受链接                                          3.链接服务器
        accept                                              connect
        建立稳定的全双工的数据传输通道              
6.通信                                              4.通信
        send recv
7.关闭socket                                        5.关闭socket
                                close
        断开连接
8.清理协议版本信息                                  6.清理协议版本信息
                                WSACleanup

媒介；


阻塞：
    阻塞函数：scanf  _getch


*/


int main()
{
    //0.确定协议版本号 
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2,2), &wsaData);
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    {
        printf("确定协议版本号失败%d\n", GetLastError());
        Sleep(5000);
        return -1;
    }
    printf("确定协议版本号成功\n");


    //1.创建socket
    SOCKET serverSocket= socket(AF_INET /* internetwork: UDP, TCP, etc. */, SOCK_STREAM/*字节流 二进制*/, IPPROTO_TCP/* tcp */);
    if (SOCKET_ERROR == serverSocket)
    {
        printf("创建socket失败%d\n", GetLastError());

        //8.清理协议版本信息
        WSACleanup();

        Sleep(5000);
        return -1;
    }
    printf("创建socket成功\n");


    //2..创建服务器协议地址族
    SOCKADDR_IN sadder = { 0 };
    sadder.sin_family = AF_INET/* internetwork: UDP, TCP, etc. */;      //与第一个参数一致
    sadder.sin_addr.S_un.S_addr = inet_addr("10.133.98.104");      //ip地址      作用是区分主机
    sadder.sin_port = htons(9527);  //大小端模式   一般pc机都是小端      网络服务器是unix系统，是大端       所以把整数从小端转成大端
            //我们电脑一般的端口号是65536个     并且一个应用程序绑定一个端口号    一个程序绑定了 另外一个程序就不能用了      所以使用5000以上的   10000左右的最好     数太大没什么用 数太小有可能别的程序用了   


    //3.绑定
    int r = bind(serverSocket, (struct sockaddr*)&sadder, sizeof(sadder));
    if (r == -1)
    {
        printf("绑定失败%d\n", GetLastError());

        //7.关闭socket
        closesocket(serverSocket);

        //8.清理协议版本信息
        WSACleanup();

        Sleep(5000);
        return -1;
    }
    printf("绑定成功\n");


    //4.监听
    r = listen(serverSocket, 10);
    if (r == -1)
    {
        printf("监听失败%d\n", GetLastError());

        //7.关闭socket
        closesocket(serverSocket);

        //8.清理协议版本信息
        WSACleanup();

        Sleep(5000);
        return -1;
    }
    printf("监听成功\n");


    //5.接受客户端连接
    SOCKET clientSocket = accept(serverSocket, NULL, NULL);
    if (SOCKET_ERROR == clientSocket)
    {
        printf("服务器崩溃了%d\n", GetLastError());

        //7.关闭socket
        closesocket(serverSocket);

        //8.清理协议版本信息
        WSACleanup();

        Sleep(5000);
        return -1;
    }
    printf("有客户端连接上服务器了\n");


    //6.通信      客户端发数据给服务器 服务器输出到控制台
    char buff[1024];
    while (1)
    {
        r = recv(clientSocket/*从哪里接收*/, buff/*接收到哪*/, 1023/*接收多大*/, NULL);  //和读文件一致
        if (r > 0)
        {
            buff[r] = 0; //添加结束符号   '\0'        r作为坐标刚好是末尾的下一个 所以有结束符号作用
            printf(">>%s\n", buff);

        }
        else
        {
            break;
        }
    }


    //7.关闭socket
    closesocket(serverSocket);


    //8，清理协议版本信息
    WSACleanup();

    //注意单有server    不要直接运行

    return 0;
}


